﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Elf.Data.Entity.Interfaces;
using System.Linq.Expressions;
using System.Data.Entity;

namespace Elf.Data.Entity
{
    /// <summary>
    /// A generic repository.
    /// </summary>
    /// <typeparam name="TEntity">The type of the entity.</typeparam>
    /// <typeparam name="TContext">The type of the context.</typeparam>
    public class Repository<TEntity, TContext> : RepositoryBase<TEntity, TContext>, IRepository<TEntity, TContext>
        where TEntity : class, IEntityBase, new()
        where TContext : ContextBase, new()
    {
        /// <summary>
        /// Finds all entities for a given type.
        /// </summary>
        /// <returns></returns>
        public virtual IList<TEntity> FindAll()
        {
            return DbContext.Set<TEntity>().ToList();
        }

        /// <summary>
        /// Finds all entities for a given type by a given expression.
        /// </summary>
        /// <param name="predicate">The predicate.</param>
        /// <returns></returns>
        public virtual IList<TEntity> FindBy(Expression<Func<TEntity, bool>> predicate)
        {
            if (predicate == null) throw new ArgumentNullException("predicate");

            return DbContext.Set<TEntity>().Where(predicate).ToList();
        }

        /// <summary>
        /// Finds all entities for a given type by its primary key.
        /// </summary>
        /// <param name="id">The id.</param>
        /// <returns></returns>
        public virtual TEntity FindById(object id)
        {
            return DbContext.Set<TEntity>().Find(new object[] { id });
        }

        /// <summary>
        /// Adds the specified entity.
        /// </summary>
        /// <param name="Entity">The entity.</param>
        public virtual void Add(TEntity entity)
        {
            DbContext.Set<TEntity>().Add(entity);
        }

        /// <summary>
        /// Removes the specified entity.
        /// </summary>
        /// <param name="entity">The entity.</param>
        public virtual void Remove(TEntity entity)
        {
            DbContext.Set<TEntity>().Remove(entity);
        }

        /// <summary>
        /// Return the DbSet of the specified entity.
        /// </summary>
        /// <returns></returns>
        public virtual IDbSet<TEntity> DbSet()
        {
            return DbContext.Set<TEntity>();
        }
    }
}
